/** BytePay TPDU Proxy
 *
 * Copyright (c) 2016 Lucky Byte, Inc.
 */
#include <glib.h>
#include <glib/gstdio.h>
#include <gio/gio.h>

static GSocketService *socket_server;


/* 读取客户端到请求报文
 */
static gchar *  tpdu_read_reqt(gchar             *remote_host,
                               gint               remote_port,
                               GSocketConnection *connection,
                               gint              *recv_size)
{
  GError *error = NULL;
  guint16 pkt_size;
  gchar *recv_buff;
  gint recv_size2;

  GInputStream *input =
    g_io_stream_get_input_stream(G_IO_STREAM(connection));
  GDataInputStream *data_input = g_data_input_stream_new(input);
  g_data_input_stream_set_byte_order(data_input,
                                     G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
  pkt_size = g_data_input_stream_read_uint16(data_input, NULL, &error);
  if (pkt_size == 0)
    {
      if (error)
        {
          g_warning("读取客户端报文长度错误: %s", error->message);
          g_error_free(error);
          g_object_unref(data_input);
          return FALSE;
        }
    }
  g_debug("客户端[%s][%d]发送的请求报文长度为[%d].", remote_host,
          remote_port, pkt_size);
  if (pkt_size > 4096 || pkt_size < 22)
    {
      g_warning("客户端[%s][%d]发送的报文长度[%d]无效，丢弃此请求.",
                remote_host, remote_port, pkt_size);
      g_object_unref(data_input);
      return FALSE;
    }
  recv_buff = g_malloc(pkt_size);
  recv_size2 = 0;
  while (recv_size2 < pkt_size)
    {
      gssize read_size =
        g_input_stream_read(input, recv_buff + recv_size2,
                            pkt_size - recv_size2, NULL, &error);
      if (read_size < 0)
        {
          g_warning("读客户端[%s][%d]的请求报文错误: %s", remote_host,
                    remote_port, error->message);
          g_object_unref(data_input);
          return NULL;
        }
      if (read_size == 0)
        {
          g_warning("读客户端[%s][%d]的请求报文错误: 连接已断开.",
                    remote_host, remote_port);
          g_object_unref(data_input);
          return NULL;
        }
      recv_size2 += read_size;
    }
  *recv_size = recv_size2;
  return recv_buff;
}


/* 转发到后端服务器，并接收处理结果
 */
static gchar *  tpdu_proxy(gchar *remote_host, gint remote_port,
                           gchar *recv_buff, gssize recv_size,
                           GKeyFile *ini_file)
{
  GError *error = NULL;
  gchar *value;

  gchar tpdu[11];
  for (int i = 0; i < 5; i++)
    {
      g_sprintf(tpdu + i * 2, "%02x", recv_buff[i]);
    }
  tpdu[10] = '\0';
  g_debug("客户端[%s][%d]的请求TPDU为[%s].", remote_host,
          remote_port, tpdu);
  value = g_key_file_get_string(ini_file, "TPDU", tpdu, &error);
  if (value == NULL)
    {
    }
  return NULL;
}

/* 处理客户端请求
 */
static gboolean tpdu_server_run(GThreadedSocketService *service,
                                GSocketConnection      *connection,
                                GObject                *source_object,
                                gpointer                user_data)
{
  GKeyFile *ini_file = user_data;
  GError *error = NULL;
  gchar *remote_host;
  gint remote_port;
  gchar *recv_buff;
  gint recv_size;
  gchar *resp_buff;
  gssize resp_size;

  GSocketAddress *remote_addr =
    g_socket_connection_get_remote_address(connection, &error);
  if (!remote_addr)
    {
      g_warning("获取客户端地址错误: %s", error->message);
      return FALSE;
    }
  GInetAddress *inet_addr =
    g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(remote_addr));
  remote_host = g_inet_address_to_string(inet_addr);
  remote_port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(remote_addr));
  g_object_unref(remote_addr);

  g_debug("接收客户端[%s][%d]的请求，开始处理...", remote_host, remote_port);

  recv_buff = tpdu_read_reqt(remote_host, remote_port,
                             connection, &recv_size);
  if (!recv_buff)
    return FALSE;

  g_debug("客户端[%s][%d]的请求处理完毕.", remote_host, remote_port);
  g_free(remote_host);

  return FALSE;
}


/* 启动线程网络服务器
 */
gboolean
tpdu_server_startup(gint port, GKeyFile *ini_file)
{
  GError *error = NULL;
  if (port <= 0)
    {
      g_warning("服务器监听端口[%d]无效.", port);
      return FALSE;
    }
  socket_server = g_threaded_socket_service_new(10);
  if (!g_socket_listener_add_inet_port(G_SOCKET_LISTENER(socket_server),
                                       port, NULL, &error))
    {
      g_warning("添加服务器绑定端口[%d]错误: %s", port, error->message);
      g_error_free(error);
      return FALSE;
    }
  g_signal_connect(socket_server, "run",
                   G_CALLBACK(tpdu_server_run), ini_file);
  g_socket_service_start(socket_server);
  g_debug("启动服务器成功，绑定端口[%d].", port);
  return TRUE;
}


/* 关闭服务器
 */
void
tpdu_server_shutdown()
{
  if (socket_server)
    {
      g_socket_service_stop(socket_server);
      g_object_unref(socket_server);
      socket_server = NULL;
    }
}
